package com.garbuz.svnadmin.services
{
	import actionlib.common.utils.ReflectUtil;

	import common.serialization.Serializer;

	import flash.utils.ByteArray;

	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.HTTPService;
	import mx.utils.Base64Decoder;
	import mx.utils.Base64Encoder;

	public class HTTPServiceBase
	{
		static public var defaultURL:String;
		static public var defaultErrorHandler:Function;

		private var _resultHandler:Function;
		private var _errorHandler:Function;

		public function HTTPServiceBase(resultHandler:Function = null, errorHandler:Function = null)
		{
			_resultHandler = resultHandler;
			_errorHandler = errorHandler;
		}

		public function doCall(methodName:String, methodArgs:Array):void
		{
			var serviceName:String = ReflectUtil.getClassName(this);
			var requestData:ByteArray = Serializer.encode([serviceName, methodName, methodArgs]);

			var encoder:Base64Encoder = new Base64Encoder();
			encoder.encodeBytes(requestData);

			var service:HTTPService = new HTTPService();
			service.url = defaultURL;
			service.request = {data: encoder.toString()};
			service.resultFormat = HTTPService.RESULT_FORMAT_TEXT;
			service.method = "POST";
			service.addEventListener(ResultEvent.RESULT, onResult);
			service.addEventListener(FaultEvent.FAULT, onFault);
			service.send();

			trace("HTTPService:", serviceName + "." + methodName + "(" + methodArgs.join(",") + ")");
		}

		private function onResult(e:ResultEvent):void
		{
			var prefix:String = String(e.result).substr(0, 1);
			var rawData:String = String(e.result).substr(1);

			if (prefix == "!")
				handleError(new Error(rawData));
			else if (prefix == "@")
				handleResult(rawData);
		}

		private function onFault(e:FaultEvent):void
		{
			handleError(e.fault);
		}

		private function handleResult(rawData:String):void
		{
			if (_resultHandler == null)
				return;

			var decoder:Base64Decoder = new Base64Decoder();
			decoder.decode(rawData);
			var bytes:ByteArray = decoder.toByteArray();
			var result:Object = Serializer.decode(bytes);
			_resultHandler(result);
		}

		private function handleError(error:Error):void
		{
			var handler:Function = _errorHandler || defaultErrorHandler;
			if (handler != null)
				handler(error);
		}
	}
}